package org.bjf.modules.core.web.advice;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;


/**
 * 针对@RequestBody请求的处理
 */
@ControllerAdvice
@Slf4j
public class LiveRequestBodyAdvice implements RequestBodyAdvice {

  private static final String DEFAULT_CHARSET = "UTF-8";

  @Override
  public boolean supports(MethodParameter methodParameter, Type targetType,
      Class<? extends HttpMessageConverter<?>> converterType) {
    // 可以在些写过滤条件
    return true;
  }

  @Override
  public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
      Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {

    String body = IOUtils.toString(inputMessage.getBody(), DEFAULT_CHARSET);
    log.info("request body:{}", body);
    return new InputMessage(inputMessage.getHeaders(),
        new ByteArrayInputStream(body.getBytes(DEFAULT_CHARSET)));
  }

  @Override
  public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
      Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
    return body;
  }

  @Override
  public Object handleEmptyBody(Object body, HttpInputMessage inputMessage,
      MethodParameter parameter, Type targetType,
      Class<? extends HttpMessageConverter<?>> converterType) {
    return body;
  }

  private static class InputMessage implements HttpInputMessage {

    private HttpHeaders headers;
    private InputStream body;

    public InputMessage(HttpHeaders headers, InputStream body) {
      this.headers = headers;
      this.body = body;
    }

    @Override
    public InputStream getBody() throws IOException {
      return body;
    }

    @Override
    public HttpHeaders getHeaders() {
      return headers;
    }
  }

}
